<?php
/**
 * 复杂享元模式
 *
 * 将一个对象在系统中共享，并且将其中的状态分离成不可更改状态和更改状态，整合了合成模式
 */
//抽象享元角色
abstract class Flyweight{
	//规定方法,外蕴状态可以通过参数形式传入。
	abstract public function Operation($extrinsicstate);
}
//单纯具体享元角色
class ConcreteFlyweight extends Flyweight
{
	public $name;
	//内蕴状态
	private $intrinsicstate = "localvalue";
	public $extrinsicstate;
	//实现的方法
	public function Operation($extrinsicstate)
	{
		//参数传入的外蕴状态
		$this->extrinsicstate = $extrinsicstate;
		echo "ConcreteFlyweight{$this->name}:intrinsicstate {$this->intrinsicstate},extrinsicstate {$this->extrinsicstate}".PHP_EOL;
	}
}
//享元工厂角色
class FlyweightFactory
{
	//存储所有的享元
	private $flyweights = array();
	//创建
	public function __construct()
	{

	}
	//获取flyweight方法
	public function GetFlyweight($key)
	{
		//没有合适的flyweight,则创建它。
		if(!isset($this->flyweights[$key])){
			$this->flyweights[$key] = new ConcreteFlyweight();
			$this->flyweights[$key]->name = $key;
 		}
		return $this->flyweights[$key];
	}
}
//合成模式具体享元角色
class ConcreteCompositeFlyweight extends Flyweight
{
    /* @var $flyweights Flyweight[]*/
	private $flyweights;
	//添加享元
	public function add(Flyweight $flyweight)
	{
		$this->flyweights[] = $flyweight;  
	}
	//获取外蕴状态
	public function Operation($extrinsicstate){
		foreach($this->flyweights as $flyweight)
		{
			$flyweight->Operation(--$extrinsicstate);
		}
	}
}

//客户端
$extrinsicstate = 22;
$f = new FlyweightFactory();
//在不同的flyweight实例中工作
$fa = $f->GetFlyweight("A");
//$fa->Operation(--$extrinsicstate);

$fb = $f->GetFlyweight("B");
//$fb->Operation(--$extrinsicstate);

$fc = $f->GetFlyweight("C");
//$fb->Operation(--$extrinsicstate);

$comf1 = new ConcreteCompositeFlyweight();
$comf1->add($fa);
$comf1->add($fb);

$comf2 = new ConcreteCompositeFlyweight();
$comf2->add($fb);
$comf2->add($fc);

$comf3 = new ConcreteCompositeFlyweight();
$comf3->add($comf1);

$comf4 = new ConcreteCompositeFlyweight();
$comf4->add($comf2);
$comf4->add($comf3);
$comf4->Operation(--$extrinsicstate);

echo "a = ".$fa->extrinsicstate.PHP_EOL;
echo "b = ".$fb->extrinsicstate.PHP_EOL;
echo "c = ".$fc->extrinsicstate.PHP_EOL;


